package com.biubiux2.session;

import com.biubiux2.async.FutureTaskScheduler;
import com.biubiux2.async.GamerThread;
import com.biubiux2.entity.User;
import io.netty.channel.Channel;
import io.netty.util.AttributeKey;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * 用户登录后建立
 * 用户退出登录并连接断开后销毁
 *
 * @author noexcs
 * @since 8/10/2022 2:40 PM
 */
@Slf4j
public class ServerSession {

    public static final AttributeKey<ServerSession> SESSION_ATTRIBUTE_KEY = AttributeKey.valueOf("SESSION_ATTRIBUTE_KEY");

    public static long expiredTime = TimeUnit.MINUTES.toMillis(30);

    @Setter
    @Getter
    private Channel channel;

    @Setter
    public boolean logged = true;

    public long lastReceivedTime = System.currentTimeMillis();

    public ScheduledFuture scheduledFuture;

    private String sessionId = UUID.randomUUID().toString();

    public UserTransmission userTransmission = new UserTransmission();

    private Map<String, Object> map = new HashMap<>();

    public ServerSession(Channel channel) {
        this.channel = channel;
        this.sessionId = UUID.randomUUID().toString().replaceAll("-", "");
        logged = true;
    }

    public void addToRemoveSessionService() {
        scheduledFuture = SessionMap.removeSessionService.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                long gap = System.currentTimeMillis() - lastReceivedTime;
                if (gap > ServerSession.expiredTime) {
                    GamerThread.submit(() -> {
                        // 取消定时任务
                        ServerSession.this.scheduledFuture.cancel(false);
                        if (ServerSession.this.channel != null) {
                            // 关闭连接
                            ServerSession.this.channel.close();
                            User user = ServerSession.this.userTransmission.getUser();
                            // 移除Session
                            SessionMap.getInstance().sessionMap.remove(ServerSession.this.getSessionId());
                            SessionMap.getInstance().uidSessionMap.remove(user.getUserId());
                            log.debug("用户{}({})Session 超时", user.getUsername(), user.getUserId());
                        }
                    }, userTransmission.getUser().getUserId());
                }
            }
        }, 10, 10, TimeUnit.SECONDS);
    }

    public String getSessionId() {
        return sessionId;
    }

    public void bindChannel() {
        channel.attr(SESSION_ATTRIBUTE_KEY).set(this);
    }

    public void setAttribute(String key, Object value) {
        map.put(key, value);
    }

    public Object getAttribute(String attrKey) {
        return map.get(attrKey);
    }

    public void writeAndFlush(Object msg) {
        channel.writeAndFlush(msg);
    }

    public boolean isExpired() {
        return false;
    }

    public void updateSessionId() {
        ConcurrentHashMap<String, ServerSession> sessionMap = SessionMap.getInstance().sessionMap;
        sessionMap.remove(sessionId);
        sessionId = UUID.randomUUID().toString();
        sessionMap.put(sessionId, this);
    }
}
